package com.chenyun.common.utils;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.listener.ReadListener;
import com.alibaba.excel.write.metadata.WriteSheet;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

/**
 * Excel帮助类
 *
 * @author: Lonni
 * @date: 2022/1/24 0024 15:57
 */
public class ExcelUtil {


    /**
     * 获取ExcelWriter
     * @param fileName
     * @param templatePath
     * @return
     */
    public static ExcelWriter getExcelWriter(String fileName, String templatePath){
        ExcelWriter excelWriter = EasyExcel.write(fileName).withTemplate(templatePath).build();
        return excelWriter;
    }

    /**
     * 填充数据 依赖 getExcelWriter 需要手动close
     * @param writer
     * @param writeSheet
     * @param data
     */
    public static void workFill(ExcelWriter writer, WriteSheet writeSheet, Object data){
        writer.fill(data,writeSheet);
    }



    /**
     * 方案2 分多次 填充 会使用文件缓存（省内存） jdk8
     * excel版本要求 since: 3.0.0-beta1及以上
     * @param fileName 填充后的文件名称,必须是全路径
     * @param templatePath 模版名称,必须是全路径
     * @param supplier
     */
    public static void  listFill(String fileName, String templatePath, Supplier<Object> supplier){
        EasyExcel.write(fileName)
                .withTemplate(templatePath)
                .sheet()
                .doFill(supplier);
    }

    /**
     * 填充excel 一次性填充
     * 模版规则 : 使用{}填充 ,如{name}
     *   单条数据填充 : {name}
     *   多条数据填充: {.name}  {.age} 多条数据填充需要加.
     * @param fileName 填充后的文件名称,必须是全路径
     * @param templatePath 模版名称,必须是全路径
     * @param data 带填充的数据
     */
    public static  void  listFill(String fileName, String templatePath, List<Map<String, String>> data){
        EasyExcel.write(fileName).withTemplate(templatePath).sheet().doFill(data);
    }

    /********************填充结束**********************/


    /********************读取开始**********************/

    /**
     * 读取excel内容,通过ReadListener处理读取的内容
     * @param fileName
     * @param receiveClass
     * @param readListener
     */
    public static  void doReadExcel(String fileName, Class receiveClass, ReadListener readListener){
        EasyExcel.read(fileName, receiveClass, readListener).sheet().doRead();
    }

    /********************读取结束**********************/


    /********************写入开始**********************/


    /**
     * 通过bean对象导出excel
     * @param fileName 文件名称 含路径
     * @param sheet sheet 名称
     * @param beanClass  bean class对象
     * @param data 写入数据 , list集合
     */
    public static  void writeExcelByBean(String fileName, String sheet, Class beanClass, List data){
        EasyExcel.write(fileName,beanClass).sheet(sheet).doWrite(data);
    }
    /**
     * 导出 写入数据 动态
     * @param fileName 文件名称 含路径
     * @param sheetName excel sheet 名称
     * @param header 表头名称
     * @param data 数据
     */
    public static void writeExcel(String fileName, String sheetName, List<List<String>> header, List<List<String>> data){
        EasyExcel.write(fileName).head(header).sheet(sheetName).doWrite(data);
    }

    /**
     * web下写excel 导出 直接调用response下载
     * @param fileName  文件名称,这里不含路径
     * @param sheetName excel sheet 名称
     * @param header 表头列
     * @param data 数据
     * @param response 输出流
     * @throws IOException
     */
    public static void writeExcel(String fileName, String sheetName, List<List<String>> header, List<List<String>> data, HttpServletResponse response) throws IOException {
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
        fileName= !fileName.contains(".xlsx") ?fileName+".xlsx":fileName;
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName );
        EasyExcel.write(response.getOutputStream()).head(header).sheet(sheetName).doWrite(data);
    }

    /********************写入结束**********************/






}
